package com.shinhye.elephantsafe;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.Formatter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.shinhye.elephantsafe.domain.ProcessInfo;
import com.shinhye.elephantsafe.engine.ProcessInfomations;
import com.shinhye.elephantsafe.utils.SystemInfoUtils;

public class ProcessManagerActivity extends Activity {
	private ListView lv_processlist;
	private LinearLayout ll_loading;
	private TextView tv_subtitle;
	private List<ProcessInfo> procInfos;
	private List<ProcessInfo> userProcInfos;
	private List<ProcessInfo> sysProcInfos;
	private ActivityManager am;
	private MyProcInfoAdpater adapter;
	private TextView tv_processcount;
	private TextView tv_availram;
	private long totalRAM;
	private int runningProcessCount;
	private long availRAM;
	private LinearLayout ll_toolbar;
	private boolean showsys;
	
	private Handler handler = new Handler() {

		@Override
		public void handleMessage(android.os.Message msg) {
			ll_loading.setVisibility(View.GONE);
			tv_subtitle.setVisibility(View.VISIBLE);
			lv_processlist.setVisibility(View.VISIBLE);
			ll_toolbar.setVisibility(View.VISIBLE);
			
			adapter = new MyProcInfoAdpater();
			lv_processlist.setAdapter(adapter);
			
			setTitleInfo(showsys ? runningProcessCount : runningProcessCount - sysProcInfos.size(), availRAM, totalRAM);
		};
	};
	private SharedPreferences sp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_processmanager);
		am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
		sp = getSharedPreferences("Setting", MODE_PRIVATE);
		
		ll_loading = (LinearLayout) findViewById(R.id.ll_loading);
		lv_processlist = (ListView) findViewById(R.id.lv_processlist);
		tv_subtitle = (TextView) findViewById(R.id.tv_subtitle);
		tv_processcount = (TextView) findViewById(R.id.tv_processcount);
		tv_availram = (TextView) findViewById(R.id.tv_availram);
		ll_toolbar = (LinearLayout) findViewById(R.id.ll_toolbar);
		
		runningProcessCount = SystemInfoUtils.getRunningProcessCount(this);
		availRAM = SystemInfoUtils.getAvailRAM(this);
		totalRAM = SystemInfoUtils.getTotalRAM(this);
		
		getData();

		//添加滚动监听器，从而设置当前滚动位置是系统进程还是用户进程
		lv_processlist.setOnScrollListener(new OnScrollListener() {
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
			}
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				if(userProcInfos != null && sysProcInfos != null) {
					if(firstVisibleItem > userProcInfos.size()) {
						tv_subtitle.setText("系统进程(" + sysProcInfos.size() + ")");
					} else {
						tv_subtitle.setText("用户进程(" + userProcInfos.size() + ")");
					}
				}
			}
		});
		
		//用户点击Item时弹出菜单
		lv_processlist.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position,
					long id) {
				ProcessInfo info = (ProcessInfo) lv_processlist.getItemAtPosition(position);
				if(info == null)
					return;
				if(info.getPackname().equals(getPackageName()))
					return;
				CheckBox cb_process = (CheckBox) view.findViewById(R.id.cb_process);
				info.setChecked(!cb_process.isChecked());
				cb_process.setChecked(!cb_process.isChecked());
			}
		});
		
		//长按时清理进程
		lv_processlist.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View view,
					int position, long id) {
				ProcessInfo info = (ProcessInfo) lv_processlist.getItemAtPosition(position);
				if(info == null)
					return true;
				if(info.getPackname().equals(getPackageName()))
					return true;
				am.killBackgroundProcesses(info.getPackname());
				if(info.isUserProc())
					userProcInfos.remove(info);
				else
					sysProcInfos.remove(info);

				Toast.makeText(ProcessManagerActivity.this, "结束了1个进程，共释放了" + Formatter.formatFileSize(ProcessManagerActivity.this, info.getMemsize()) + "内存", Toast.LENGTH_SHORT).show();

				runningProcessCount--;
				availRAM += info.getMemsize();
				setTitleInfo(showsys ? runningProcessCount : runningProcessCount - sysProcInfos.size(), availRAM, totalRAM);
				
				adapter.notifyDataSetChanged();
				return true;
			}
		});
	}
	
	/**
	 * A adapter to provider data for ListView.
	 * @author ShinHye
	 *
	 */
	class MyProcInfoAdpater extends BaseAdapter {

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			ViewHolder holder;
			final ProcessInfo info;
			if(position == 0) {
				TextView tv_user = new TextView(ProcessManagerActivity.this);
				tv_user.setTextColor(Color.WHITE);
				tv_user.setBackgroundColor(Color.MAGENTA);
				tv_user.setPadding(2, 0, 0, 0);
				tv_user.setTextSize(16);
				tv_user.setText("用户进程(" + userProcInfos.size() + ")");
				return tv_user;
			} else if(position == userProcInfos.size() + 1) {
				TextView tv_sys = new TextView(ProcessManagerActivity.this);
				tv_sys.setTextColor(Color.WHITE);
				tv_sys.setBackgroundColor(Color.MAGENTA);
				tv_sys.setPadding(2, 0, 0, 0);
				tv_sys.setTextSize(16);
				tv_sys.setText("系统进程(" + sysProcInfos.size() + ")");
				return tv_sys;
			} else if(position < userProcInfos.size() + 1) {
				info = userProcInfos.get(position - 1);
			} else {
				int newPos = position - 1 - userProcInfos.size() - 1;
				info = sysProcInfos.get(newPos);
			}
			if(convertView != null && convertView instanceof RelativeLayout) {
				view = convertView;
				holder = (ViewHolder) view.getTag();
			} else {
				view = View.inflate(ProcessManagerActivity.this, R.layout.item_processinfolist, null);
				holder = new ViewHolder();
				holder.iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
				holder.tv_procname = (TextView) view.findViewById(R.id.tv_procname);
				holder.tv_memsize = (TextView) view.findViewById(R.id.tv_memsize);
				holder.cb_progress = (CheckBox) view.findViewById(R.id.cb_process);
				view.setTag(holder);
			}
			
			holder.iv_icon.setImageDrawable(info.getIcon());
			holder.tv_procname.setText(info.getName());
			holder.tv_memsize.setText(Formatter.formatFileSize(ProcessManagerActivity.this, info.getMemsize()));
			holder.cb_progress.setChecked(info.isChecked());
			holder.cb_progress.setVisibility(View.VISIBLE);
			holder.cb_progress.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					info.setChecked(!info.isChecked());
				}
			});
			if(info.getPackname().equals(getPackageName()))
				holder.cb_progress.setVisibility(View.INVISIBLE);
			
			return view;
		}
		
		@Override
		public int getCount() {
			showsys = sp.getBoolean("showsystemprocess", true);
			if(!showsys || sysProcInfos.size() == 0) {
				return userProcInfos.size() + 1;
			}
			else {
				return userProcInfos.size() + 1 + sysProcInfos.size() + 1;
			}
		}

		@Override
		public Object getItem(int position) {
			if(position == 0) {
				return null;
			} else if(position == userProcInfos.size() + 1) {
				return null;
			} else if(position < userProcInfos.size() + 1) {
				return userProcInfos.get(position - 1);
			} else {
				return sysProcInfos.get(position - 1 - userProcInfos.size() - 1);
			}
		}
		
		@Override
		public long getItemId(int position) {
			return 0;
		}
	}
	
	static class ViewHolder {
		ImageView iv_icon;
		TextView tv_procname;
		TextView tv_memsize;
		CheckBox cb_progress;
	}

	/**
	 * Start a new thread to update UI while loading a lot of data.
	 */
	public void getData() {
		lv_processlist.setVisibility(View.INVISIBLE);
		ll_loading.setVisibility(View.VISIBLE);
		tv_subtitle.setVisibility(View.INVISIBLE);
		new Thread(new Runnable() {
			@Override
			public void run() {
				
				procInfos = ProcessInfomations.getAllProcessInfos(ProcessManagerActivity.this);
				userProcInfos = new ArrayList<ProcessInfo>();
				sysProcInfos = new ArrayList<ProcessInfo>();
				for(ProcessInfo info : procInfos) {
					if(info.isUserProc())
						userProcInfos.add(info);
					else
						sysProcInfos.add(info);
				}
				
				handler.sendEmptyMessage(0);
			}
		}).start();
	}

	public void selectall(View v) {
		for(ProcessInfo info : userProcInfos) {
			if(info.getPackname().equals(getPackageName()))
				continue;
			info.setChecked(true);
		}
		if(showsys) {
			for(ProcessInfo info : sysProcInfos) {
				info.setChecked(true);
			}
		}
		adapter.notifyDataSetChanged();
	}
	
	public void selectobverse(View v) {
		for(ProcessInfo info : userProcInfos) {
			if(info.getPackname().equals(getPackageName()))
				continue;
			info.setChecked(!info.isChecked());
		}
		if(showsys) {
			for(ProcessInfo info : sysProcInfos) {
				info.setChecked(!info.isChecked());
			}
		}
		adapter.notifyDataSetChanged();
	}
	
	public void killselect(View v) {
		int total = 0;
		long memrele = 0;
		Iterator<ProcessInfo> userIter = userProcInfos.iterator();
		Iterator<ProcessInfo> sysIter = sysProcInfos.iterator();
		while(userIter.hasNext()) {
			ProcessInfo info = userIter.next();
			if(info.getPackname().equals(getPackageName()))
				continue;
			if(info.isChecked()) {
				total++;
				memrele += info.getMemsize();
				am.killBackgroundProcesses(info.getPackname());
				userIter.remove();
			}
		}
		while(sysIter.hasNext()) {
			ProcessInfo info = sysIter.next();
			if(info.isChecked()) {
				total++;
				memrele += info.getMemsize();
				am.killBackgroundProcesses(info.getPackname());
				sysIter.remove();
			}
		}
		
		Toast.makeText(this, "结束了" + total + "个进程，共释放了" + Formatter.formatFileSize(this, memrele) + "内存", Toast.LENGTH_SHORT).show();
		
		runningProcessCount -= total;
		availRAM += memrele;
		setTitleInfo(showsys ? runningProcessCount : runningProcessCount - sysProcInfos.size(), availRAM, totalRAM);
		
		adapter.notifyDataSetChanged();
	}
	
	public void wipesetting(View v) {
		Intent intent = new Intent(this, ProcManagerSettingActivity.class);
		startActivityForResult(intent, 101);
	}
	
	/**
	 * Set the process count and the memory information into the subtitle. 
	 * @param procNum Process count
	 * @param RamAvail Available ram
	 * @param RamTotal Total ram
	 */
	public void setTitleInfo(int procNum, long RamAvail, long RamTotal) {
		tv_processcount.setText("运行中进程:" + procNum + "个");
		tv_availram.setText("剩余/总内存:" + Formatter.formatFileSize(this, RamAvail) + "/" + Formatter.formatFileSize(this, RamTotal));
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		showsys = sp.getBoolean("showsystemprocess", true);
		setTitleInfo(showsys ? runningProcessCount : runningProcessCount - sysProcInfos.size(), availRAM, totalRAM);
		adapter.notifyDataSetChanged();
	}
}
